package xyz.shenmegui.foodcheckserver.controller;

import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import xyz.shenmegui.foodcheckserver.DO.Compound;
import xyz.shenmegui.foodcheckserver.DO.Food;
import xyz.shenmegui.foodcheckserver.DO.Menu;
import xyz.shenmegui.foodcheckserver.DO.Record;
import xyz.shenmegui.foodcheckserver.DO.User;
import xyz.shenmegui.foodcheckserver.VO.CollectionList;
import xyz.shenmegui.foodcheckserver.annotation.Login;
import xyz.shenmegui.foodcheckserver.annotation.LoginUser;
import xyz.shenmegui.foodcheckserver.http.HttpResponse;
import xyz.shenmegui.foodcheckserver.service.CompoundService;
import xyz.shenmegui.foodcheckserver.service.FoodService;
import xyz.shenmegui.foodcheckserver.service.RecordService;
import xyz.shenmegui.foodcheckserver.service.*;
import xyz.shenmegui.foodcheckserver.utils.JWTUtil;
import xyz.shenmegui.foodcheckserver.utils.ObjectUtil;
import xyz.shenmegui.foodcheckserver.utils.PythonUtil;
import xyz.shenmegui.foodcheckserver.utils.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/search")
public class SearchController {

    @Autowired
    private PythonUtil pythonUtil;

    @Autowired
    private CompoundService compoundService;

    @Autowired
    private RecordService recordService;

    @Autowired
    private JWTUtil jwtUtil;

    @Autowired
    private FoodService foodService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private CollectionService collectionService;

    @GetMapping("/keyword")
    public HttpResponse searchByKeywordGet(@RequestParam("keyword") String keyword) {
        // 对象声明与初始化
        HashMap<String, Object> result = new HashMap<>();
        // 数据库中根据前端传入的 keyword 查询对应食物
        List<Food> foods =  foodService.searchFoodListByName(keyword);
        // 数据库中有，则返回，没有则执行爬虫
        if (foods.size() == 0) {
            // 运行 python 爬虫
            String resp = pythonUtil.Run("nutrition", keyword);
            // 解析 python 爬虫返回结果
            if (!resp.equals("[]")) {
                resp = resp.replace("'", "\"").replace("[", "").replace("]", "");
                String[] arr = resp.split("(?<=}),");
                for (String s: arr) {
                    // json 解析成对应的对象
                    Food food = JSONObject.parseObject(s, Food.class);
                    foods.add(food);
                }
            }
        }
        for (Food food : foods) {
            // 搜索次数 + 1
            int nums = food.getFnums() + 1;
            food.setFnums(nums);
        }
        if (foods.size() > 0) {
            // 更新或插入数据库中
            foodService.updateOrFoods(foods);
        }
        // 返回结果
        return HttpResponse.okWithData(foods);
    }

    @Login
    @PostMapping("/keyword")
    public HttpResponse searchByKeywordPost(@RequestParam("keyword") String keyword, @LoginUser User user) {
        HttpResponse httpResponse = searchByKeywordGet(keyword);
        List<Compound> compounds = (List<Compound>) httpResponse.get("data");
        // 将记录保存到个人搜索记录中
//        System.out.println(user);
        if (compounds.size() > 0) {
            Record record = new Record();
            record.setUid(user.getId());
            record.setName(keyword);
            StringBuilder builder = new StringBuilder();
            for (Compound compound : compounds) {
                builder.append(compound.getId());
                builder.append(",");
            }
            builder.deleteCharAt(builder.length() - 1);
            record.setCid(builder.toString());
            recordService.insert(record);
        }
        return httpResponse;
    }

    @GetMapping("/img")
    public HttpResponse searchByImageGet(@RequestParam("Image") MultipartFile multipartFile, HttpServletRequest request) {
        String realPath = request.getSession().getServletContext().getRealPath("/img/");
        List<Compound> compounds = new ArrayList<>();
        File folder = new File(realPath);
        String filePath = "";
        if (!folder.isDirectory()) {
            folder.mkdirs();
        }
        String oldName = multipartFile.getOriginalFilename();
        String newName = UUID.randomUUID() + oldName.substring(oldName.lastIndexOf("."));
        try {
            File newImg = new File(folder, newName);
            if (!newImg.exists()) {
                // System.out.println(newImg.getAbsolutePath());
                multipartFile.transferTo(newImg);
                filePath = realPath + newName;
            } else {
                return HttpResponse.error("图片上传失败");
            }
            // 保存图片，并通过python调用模型解析图片中文字
            String[] args = {filePath};
//            System.out.println(Arrays.toString(args));
            String resp = pythonUtil.Run("ocr", args);
            System.out.println("result" + resp);
            // 对返回内容处理
            if (resp != null && !resp.equals("")) {
                // 对返回内容处理
                String[] comArray = resp.replace('，', '、').replace(',', '、').split("、");
                for (String com: comArray) {
                    Compound compound = null;
                    compoundService.selectByNameE(com);
                    if (com.matches("[a-zA-Z]+")) {
                        compound = compoundService.selectByEnNameE(com);
                    } else {
                        compound = compoundService.selectByNameE(com);
                    }
                    if (compound != null) {
                        // 数据库中有
                        compounds.add(compound);
                    } else {
                        // 没有则通过爬虫爬取
                        String resp_c = pythonUtil.Run("food_additive_crawler", com);
                        System.out.println(resp_c);
                        compound = compoundService.selectByNameE(com);
                        if (compound != null) {
                            // 数据源中有
                            compounds.add(compound);
                        }
                    }
                }
            }
            return HttpResponse.okWithData(compounds);
        } catch (FileSizeLimitExceededException e) {
            e.printStackTrace();
            return HttpResponse.error("上传图片过大");
        } catch (IOException e) {
            e.printStackTrace();
            return HttpResponse.error("上传失败");
        }
    }

    @PostMapping("/img")
    public HttpResponse searchByImagePost(@RequestParam("Image") MultipartFile multipartF, HttpServletRequest request) {
        HttpResponse httpResponse = searchByImageGet(multipartF, request);
        String token = request.getHeader("token");
        List<Compound> compounds = (List<Compound>) httpResponse.get("data");
        if (token != null && !token.equals("") && compounds.size() > 0) {
            Claims userid = jwtUtil.getClaimsToken(token);
            int id = Integer.parseInt(userid.getSubject());
            // 将记录保存到个人搜索记录中
            Record record = new Record();
            record.setUid(id);
            record.setName(compounds.get(0).getName());
            StringBuilder builder = new StringBuilder();
            for (Compound compound : compounds) {
                builder.append(compound.getId());
                builder.append(",");
            }
            builder.deleteCharAt(builder.length() - 1);
            record.setCid(builder.toString());
            recordService.insert(record);
        }
        return httpResponse;
    }
    @GetMapping("/searchFoodByName")
    public HttpResponse searchFoodByName(@RequestParam("name") String name) {
        return HttpResponse.ok(foodService.searchFoodByName(name));
    }

    @GetMapping("/getFoodByName")
    public HttpResponse getFoodByName(@RequestParam("name") String name) {
        Assert.state(StringUtils.isNotEmpty(name), "Food Name is empty!");
        Map foodByName = foodService.searchFoodByName(name);
        return HttpResponse.ok(foodByName);
    }

    @GetMapping("/getCollectByUserId")
    public HttpResponse getCollectById(@RequestParam("userId") Integer userId) {
        Assert.state(ObjectUtil.isNotNull(userId) && userId > 0,
                     "User ID is not exist or not bigger than 0!");
        CollectionList collectionList = collectionService.getCollectionByUserId(userId);
        return HttpResponse.okWithData(collectionList);
    }

    @RequestMapping("/top10")
    public HttpResponse getTop10() {
        // 对象声明与初始化
        HashMap<String, Object> result = new HashMap<>();
        // 查询搜索次数前十的数据
        result.put("top10", foodService.selectTop10());
        // 返回结果
        return HttpResponse.ok(result);
    }
}
